package com.thoughtful.serialize.kyro;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.thoughtful.remoting.dto.RpcRequest;
import com.thoughtful.remoting.dto.RpcResponse;
import com.thoughtful.serialize.Serializer;
import com.thougtful.exception.SerializeException;

/**
 * Kryo序列化类，Kryo的序列化效率很高，但只与Java语言兼容
 *
 * @author yushun
 * @createTime 2022/10/17 - 17:17
 **/
public class KyroSerializer implements Serializer {

    private final ThreadLocal<Kryo> kryoThreadLocal = ThreadLocal.withInitial(() -> {
        Kryo kryo = new Kryo();
        kryo.register(RpcRequest.class);
        kryo.register(RpcResponse.class);
        return kryo;
    });

    @Override
    public byte[] serializer(Object obj) {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             Output output = new Output(byteArrayOutputStream)) {
            Kryo kryo = kryoThreadLocal.get();
            // Object -> byte: 将对象序列化为 byte 数组
            kryo.writeObject(output, obj);
            kryoThreadLocal.remove();
            return output.toBytes();
        } catch (Exception e) {
            throw new SerializeException("Serialization failed", e);
        }
    }

    @Override
    public <T> T deserializer(byte[] bytes, Class<T> clazz) {
        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
             Input input = new Input(byteArrayInputStream)) {
            Kryo kryo = kryoThreadLocal.get();
            T result = kryo.readObject(input, clazz);
            kryoThreadLocal.remove();
            return result;
        } catch (Exception e) {
            throw new SerializeException("Deserialization failed", e);
        }
    }
}
